package com.miplus.ccrm.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class JPubUtils {
    private static final Logger logger = LoggerFactory.getLogger(JPubUtils.class);

    public static String jwt_Secret="";

    //Token默认12小时
    public static int jwt_expiration=43200;

    public static String jwt_token="";

    public static int login_maxfailtimes=5;

    //分钟，默认365天
    public static int login_failLockSapn=525600;

    public static boolean login_allowdefaultpwd=false;
    public static String login_defaultpwd="88888888";

    //密码过期最长时间=90天,2024-09-23
    public static Integer login_pwdexpiration=90;

    //检测新密码不重复历史
    public static Integer login_norepeathist=6;

    public static String token_userheader="online_@";
    public static String token_header="token_@@Bearer ";

    public static String STAR_PHN="phone";
    public static String STAR_IDNO="idno";
    public static String STAR_CARD="cardno";

    //==2023-06-09
    //默认一次手动分案最多20w条，
    public static Integer distMaxCount=200000;

    //默认案件导出最大2w条，
    public static Integer exportMaxCount=20000;

    //分案时效，默认2小时
    public static Integer distExpiration=3600;

    //短信验证码保存标识,2024-06-18
    public static String VCODE_IDEN="identifyingcode_";

    //默认5分钟
    public static Integer vcodeExpiration=300;

    //同时只允许一个大批量回收处理
    public static String recvProcessKey="batchrecy_processkey";

    //同时只允许一个大批量分案处理
    public static String distProcessKey="batchdist_processkey";

    //预分案或分配操作
    public static final int  PRE_OPERATE=1;

    //分案/分配模式=3，按案件比例分案
    public static final int DIST_MODE_CASERADIO=3;

    //分案/分配模式=2，按金额比例分案
    public static final int DIST_MODE_AMTRADIO=2;

    //回收到组
    public static final int RECY_MODE_GROUP=1;

    //回收到案件总池
    public static final int RECY_MODE_TOP=2;

    //系统类别，crd=信用卡类,iou=合同借据类
    public static EnumSysType enSysType=EnumSysType.ious;

    public static String myLocalHost="";

    public static boolean IsEmpty(String str)
    {
        return (str == null ||str.length()==0) ? true : false;
    }

    public static boolean IsTrimEmpty(String str)
    {
        if(IsEmpty(str)) return true;
        if(IsEmpty(str.trim())) return true;
        return false;
    }

    public static boolean IsEmpty(Integer i){
        if(i==null) return true;
        return  false;
    }

    public static boolean IsEmpty(Date d){
        if(d==null) return true;
        return  false;
    }

    public static boolean IsEmpty(List ll){
        if(ll==null) return true;
        if(ll.isEmpty()) return true;
        if(ll.size()==0) return true;
        return  false;
    }

    public static boolean IsEmpty(Object o)
    {
        return (o==null) ? true : false;
    }

    public static boolean IsNotEmpty(String str){
        return !IsEmpty(str);
    }

    public static boolean IsNotEmpty(Integer i){
        return !IsEmpty(i);
    }

    public static boolean IsNotEmpty(List ll){
        return !IsEmpty(ll);
    }

    public static boolean IsNotEmpty(Date d){
        return !IsEmpty(d);
    }

    public static boolean IsNotEmpty(Object o){
        return !IsEmpty(o);
    }

    public static boolean IsEqual(Integer val1,Integer val2)
    {
        if(val1==null||val2==null) return false;
        if(val1.equals(val2)) return true;
        return  false;
    }

    public static boolean IsEqual(String str1,String str2)
    {
        if(IsEmpty(str1)){
            if(IsEmpty(str2))
                return true;
            else return false;
        }

        return (str1.equals(str2));
    }

    public static boolean IsNotEqualAndNotNull(String str1,String str2)
    {
        if(IsEmpty(str1)) return false;

        return !IsEqual(str1,str2);
    }

    public static boolean IsEqual(String str1,int ival)
    {
        return IsEqual(str1,String.format("%d",ival));
    }

    public static boolean IsEqual(Date day1,Date day2)
    {
        String s1=DateToString(day1);
        String s2=DateToString(day2);
        return IsEqual(s1,s2);
    }

    public static boolean IsEqual(BigDecimal val1,BigDecimal val2)
    {
        if(val1==null&&val2==null) return true;
        if(val1==null||val2==null) return false;
        if(val1.equals(val2)) return true;
        return  false;
    }

    public static boolean IsEqual(Double val1,Double val2)
    {
        if(val1==null&&val2==null) return true;
        if(val1==null||val2==null) return false;
        if(val1.equals(val2)) return true;
        return  false;
    }

    public static String Trim(String s){
        if(s==null) return null;
        return s.trim();
    }

    public static int StringToInt(String val)
    {
        int v=0;
        if(IsEmpty(val)) return 0;

        try{
            v=Integer.parseInt(val);
        }
        catch(NumberFormatException e){
            v=0;
        };

        return v;
    }

    public static int ObjectToInt(Object val)
    {
        int v=0;
        if(val==null) return 0;

        try{
            v=Integer.parseInt(val.toString());
        }
        catch(NumberFormatException e){
            v=0;
        };

        return v;
    }

    public static String ObjectToString(Object val)
    {
        String v="";
        if(val==null) return "";

        try{
            v=val.toString();
        }
        catch(NumberFormatException e){
            v="";
        };

        return v;
    }

    public static long StringToLong(String val)
    {
        long v=0;
        if(IsEmpty(val)) return 0;

        try{
            v=Long.parseLong(val);
        }
        catch(NumberFormatException e){
            v=0;
        };

        return v;
    }

    public static double StringToDouble(String val)
    {
        double v=0.0;
        if(IsEmpty(val)) return v;

        try{
            v=Double.parseDouble(val);
        }
        catch(NumberFormatException e){
            v=0.0;
        };

        return v;
    }

    public static double ObjectToDouble(Object val)
    {
        if(val==null) return 0.0;
        return StringToDouble(val.toString());
    }

    public static boolean StringToBool(String val)
    {
        if(IsEmpty(val)) return false;

        String ret = val.toUpperCase();
        if (ret.equals("TRUE") || ret.equals("1") || ret.equals("Y") || ret.equals("YES") || ret.equals("T"))
            return true;

        return false;
    }

    public static String BoolToString(String val)
    {
        if(IsEmpty(val)) return "0";

        String ret = val.toUpperCase();
        if (ret.equals("TRUE") || ret.equals("1") || ret.equals("Y") || ret.equals("YES") || ret.equals("T"))
            return "1";

        return "0";
    }

    public static Date StringToDate(String val)
    {
        if(IsTrimEmpty(val)) return null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            if(val.length()==16){
                sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            }
            else if(val.length()>16){
                sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }

            return sdf.parse(val);
        }
        catch (Exception e){
            logger.warn("StringToDate.Err:{}",val);
            return null;
        }
    }

    public static Date GetToday() {
        try{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            //String today=formatter.format(new Date())+" 00:00:00";
            //不能加时间，否则就变成当前时间了
            String today = sdf.format(new Date());
            return sdf.parse(today);
        }
        catch (Exception e){
            logger.warn("GetToday.Err:{}",e.getMessage());
            return null;
        }
    }

    public static String DateToString(Date val)
    {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.format(val);
        }
        catch (Exception e){
            logger.warn("DateToString.Err:{}",val);
            return null;
        }
    }

    public static String DTimeToString(Date val)
    {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(val);
        }
        catch (Exception e){
            logger.warn("DTimeToString.Err:{}",val);
            return null;
        }
    }

    public static String DTimeToString(Object val)
    {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(val);
        }
        catch (Exception e){
            logger.warn("DTimeToString.Err:{}",val);
            return null;
        }
    }

    public static int DayDifference(Date startdt,Date enddt)
    {
        int iday=0;
        Date nextDay=startdt;
        while(nextDay.before(enddt)){
            Calendar cld=Calendar.getInstance();
            cld.setTime(nextDay);
            cld.add(Calendar.DATE,1);
            nextDay=cld.getTime();
            iday++;
        }
        return iday;
    }

    public static String getReqIpAddr(HttpServletRequest request) {
        try {
            if(request==null) return "";

            String ip = request.getHeader("x-forwarded-for");
            if (ip == null || ip.length() == 0 || "unknow".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            // 多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
            if (ip != null && ip.length() > 15) {
                if (ip.indexOf(",") > 0) {
                    ip = ip.substring(0, ip.indexOf(","));
                }
            }
            return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
        }
        catch(Exception e){
            logger.error("getReqIpAdd",e);
            return "-";
        }
    }

    public static String getReqIpAddr() {
        HttpServletRequest h=((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        return getReqIpAddr(h);
    }

    public static void PrintError(String title,Exception e)
    {
        logger.error("{} Error:{}",title,e);
    }

    public static void PrintInfo(String title,String msg)
    {
        logger.info("{}:{}",title,msg);
    }

    public static void PrintWarn(String title,String msg)
    {
        logger.warn("{}:{}",title,msg);
    }

    public static String getToken(HttpServletRequest request)
    {
        String token = request.getHeader("authorization");
        if(IsNotEmpty(token)){
            return token.substring(7);
        }
        else{
            //2024-07-22
            logger.error("Token:authorization isEmpty");
            PrintHeader(request);
        }

        return "";
    }

    public static void PrintHeader(HttpServletRequest request)
    {
        try {
            //2024-07-22
            Enumeration<String> enumeration = request.getHeaderNames();
            while (enumeration.hasMoreElements()) {
                String name = enumeration.nextElement();
                String value = request.getHeader(name);
                logger.info("{}={}", name, value);
            }
        }
        catch (Exception e){
            logger.warn("PrintHeader:",e);
        }
    }

    public static String getOnlineTokenKey(String usrid)
    {
        return token_userheader+usrid;
    }

    public static String getTokenKey(String token)
    {
        return token_header+token;
    }

    public static long getTimeSpan(String ts)
    {
        if(IsEmpty(ts)) return 0;
        long ln=StringToLong(ts);
        return ln>0?System.currentTimeMillis()-ln:0;
    }

    public static void Init(Environment environment)
    {
        logger.info("PubUtils.Init...");
        jwt_Secret = environment.getProperty("ccrm.security.jwt.secret");
        int expiration = StringToInt(environment.getProperty("ccrm.security.jwt.expiration"));
        if(expiration>0){
            jwt_expiration=expiration;
        }
        expiration = StringToInt(environment.getProperty("ccrm.security.loginmaxfailtimes"));
        if(expiration>0){
            login_maxfailtimes=expiration;
        }

        String s = environment.getProperty("ccrm.security.allowdefaultpwd");
        if(IsNotEmpty(s)){
            login_allowdefaultpwd=StringToBool(s);
        }
        s=environment.getProperty("ccrm.security.jwt.token");
        if(IsNotEmpty(s)) {
            jwt_token = s;
        }

        s=environment.getProperty("ccrm.security.initpwd");
        if(IsNotEmpty(s)) {
            login_defaultpwd = s.trim();
        }

        s=environment.getProperty("ccrm.distmaxcount");
        if(IsNotEmpty(s)) {
            distMaxCount = StringToInt(s.trim());
        }

        s=environment.getProperty("ccrm.exportmaxcount");
        if(IsNotEmpty(s)) {
            exportMaxCount = StringToInt(s.trim());
        }
        s=environment.getProperty("ccrm.vcodeexpiration");
        if(IsNotEmpty(s)) {
            vcodeExpiration = StringToInt(s.trim());
        }

        s=environment.getProperty("ccrm.security.loginfaillockspan");
        if(IsNotEmpty(s)) {
            login_failLockSapn = StringToInt(s.trim());
        }
        s=environment.getProperty("ccrm.security.pwd.expiration");
        if(IsNotEmpty(s)) {
            login_pwdexpiration = StringToInt(s.trim());
        }
        s=environment.getProperty("ccrm.system.type");
        if(IsNotEmpty(s)) {
            if(JPubUtils.IsEqual(s,EnumSysType.ious.name)) {
                enSysType = EnumSysType.ious;
            }
            else{
                enSysType = EnumSysType.credit;
            }
        }
        s=environment.getProperty("ccrm.localhost");
        if(IsNotEmpty(s)) {
            myLocalHost = s.trim();
        }
        logger.info("Init:jwt.expiration={},maxfailtimes={},allowdefaultpwd={},distmaxcount={},exportmaxcount={},vcodeExpiration={},loginfaillockspan={},pwdexpiration={},norepeathist={},systype={},host={}",
                jwt_expiration, login_maxfailtimes, login_allowdefaultpwd,distMaxCount,
                exportMaxCount,vcodeExpiration,login_failLockSapn,login_pwdexpiration,
                login_norepeathist,enSysType.name,myLocalHost
        );

        if(logger.isDebugEnabled()) {
            logger.debug("Init:jwt.secret={}", jwt_Secret);
        }
        logger.info("Init:token={}",jwt_token);
    }

    public static Date addMonths(Date date, int months)
    {
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH,months);
        return calendar.getTime();
    }

    public static Date addDays(Date date, int days)
    {
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE,days);
        return calendar.getTime();
    }

    public static Date addMinute(Date date, int m)
    {
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE,m);
        return calendar.getTime();
    }

    public static String getLocalIpAddr() {
        try {
            InetAddress ip4 = Inet4Address.getLocalHost();
            String ip=ip4.getHostAddress();

            logger.info("getLocalIpAddr",ip);

            return ip;
        } catch (UnknownHostException e) {
            PrintError("getLocalIpAddr",e);
        }
        return "";
    }

    public static String getInString(List<String> ls)
    {
        if(ls==null||ls.size()==0)
            return "";
        String s= String.join("','",ls);
        return String.format("%s",s);
    }

    public static String getInString(String vs)
    {
        if(JPubUtils.IsEmpty(vs)) return "";
        String[] ls=vs.split(",");
        if(ls.length<=1) return vs;
        String s= String.join("','",ls);
        return String.format("%s",s);
    }

    public static List<String> getInList(String vs)
    {
        if(JPubUtils.IsEmpty(vs)) return null;
        String[] ls=vs.split(",");
        if(ls.length<=1) return null;
        List t=new ArrayList();
        for(String s : ls){
            t.add(s);
        }
        return t;
    }

    public static String getStarString(String name,String val)
    {
        String ret=val;
        if(IsEmpty(val)) return "";
        if(val.length()<6) return val;

        if(name.equals(STAR_PHN)){
            ret=val.substring(0,3)+"****"+val.substring(8);
        }
        else if(name.equals(STAR_IDNO)){
            ret=val.substring(0,6)+"********"+val.substring(15);
        }
        else if(name.equals(STAR_CARD)){
            ret=val.substring(0,4)+"********"+val.substring(13);
        }
        return ret;
    }

    public static String BilldayToStartday(String day)
    {
        if(IsEmpty(day)) return "";

        try{
            Date d=StringToDate(day);
            d=addMonths(d,-1);
            d=addDays(d,1);
            return DateToString(d);
        }
        catch(NumberFormatException e){
            logger.warn("DTimeToString.Err:{}",day);
            return "";
        }
    }

    public static Integer StrDateToInt(String d)
    {
        String s=d.replace("-","");
        return StringToInt(s);
    }

    public static boolean hasValue(List<String> list,String val)
    {
        if(JPubUtils.IsEmpty(list)) return false;
        return list.contains(val);
    }

    public static String RTrimZero(String val)
    {
        if(IsEmpty(val)) return val;
        return val.replaceAll("0+$","");
    }

    public static String LTrimZero(String val)
    {
        if(IsEmpty(val)) return val;
        return val.replaceAll("^0*","");
    }

    public static String getVCodeIden(String usrid)
    {
        return VCODE_IDEN+usrid;
    }

    public static String getExpTempID(String filename,String fileiden)
    {
        String ret=fileiden;
        if(!JPubUtils.IsEmpty(filename)){
            ret=filename.replace(".xlsx","");
        }
        return ret;
    }

    public static String getExpFileName(String filename,String fileiden)
    {
        String ret=filename;
        if(JPubUtils.IsEmpty(filename)||(!filename.endsWith(".xlsx"))){
            DateTimeFormatter sdf=DateTimeFormatter.ofPattern("HHmmss");
            ret=fileiden+ LocalTime.now().format(sdf)+".xlsx";
        }
        return ret;
    }

    public static HashMap toExportMap(Object obj){
        HashMap map = new HashMap<>();
        Class<?> clazz = obj.getClass();
        try {
            for (Field field : clazz.getDeclaredFields()) {
                //设置访问权限，因为有些字段可能是私有的
                field.setAccessible(true);
                // 获取字段名称和值
                String fieldName = field.getName();
                Object value = field.get(obj);
                map.put(fieldName, value);
            }
            return map;
        }
        catch (IllegalAccessException e){
            logger.warn("toExportMap:{}",e.getMessage());
            return null;
        }
    }

    //得到控制案件查看权限SQL
    public static String getPuvViewSql(String $usrid)
    {
        //数据库尽量不要使用函数，否则慢,尤其TDSQL
        //.apply("fi_hasFiCaseView({0},t.creditcaseid,t.status,t.sendtodept,t.sendtousr)>0", $usrid)
        return String.format("((t.status in(2,9) and t.sendtousr='%s') or exists (SELECT 1 FROM sys_grpmgr mg WHERE mg.grpmanagerid = '%s' AND mg.grpid = t.sendtodept))",$usrid,$usrid);
    }

    public static String getSerialNumber()
    {
        Date d=new Date();
        String r=Long.toString(d.getTime());
        Random random=new Random();
        Integer i=random.nextInt(9000)+1000;
        return r+i.toString();
    }

    public static BigDecimal ToBigDecimal(Object val)
    {
        if (val == null) {
            return BigDecimal.ZERO;
        }
        try {
            if (val instanceof BigDecimal) {
                return (BigDecimal) val;
            } else if (val instanceof Number) {
                return BigDecimal.valueOf(((Number) val).doubleValue());
            } else if (val instanceof String) {
                return new BigDecimal((String) val);
            } else {
                return new BigDecimal(val.toString());
            }
        } catch (NumberFormatException e) {
            return BigDecimal.ZERO;
        }
    }

    public static BigDecimal ToBigDecimal(BigDecimal val)
    {
        if(val==null) return BigDecimal.ZERO;
        return val;
    }

    public static String getLocalIPAddr()
    {
        try {
            if(IsEmpty(myLocalHost)) {
                InetAddress localHost = InetAddress.getLocalHost();
                myLocalHost = localHost.getHostAddress();
            }
        } catch (UnknownHostException e) {
            logger.warn("getLocalIPAddr.Err:{}", e);
        }

        return myLocalHost;
    }
}
